home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / answrbok / 3_11.lha / 3_11 / 3_11c.c < prev    next >
Text File  |  1993-08-08  |  3KB  |  152 lines

  1. * Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */
  2. * The C++ Answer Book */
  3. * Tony Hansen */
  4. * All rights reserved. */
  5. / Convert a string of signed digits into an integer.
  6. / Hex and octal prefixes are allowed, as well as
  7. / character constants.
  8. /  Version 3
  9. define NO_ISODIGIT    /* DELETE */
  10. include <ctype.h>
  11. include <limits.h>
  12. include <error.h>
  13.  
  14. / convert hexadecimal 0-9, a-f, A-F
  15. / to its numeric value
  16. nline int hexvalue(char c)
  17.  
  18.    if (isdigit(c))
  19. return c - '0';
  20.  
  21.    else if (c >= 'a' && c <= 'f')
  22. return c - 'a' + 10;
  23.  
  24.    else /* (c >= 'A' && c <= 'F') */
  25. return c - 'A' + 10;
  26.  
  27.  
  28. / return true if c is an octal digit
  29. nline int isodigit(char c)
  30.  
  31.    return isdigit(c) && c < '8';
  32.  
  33.  
  34. include "3_11e1.c"    /* EXPAND defines TWOSCOMPLEMENT */
  35.  
  36. nt atoi(const char *s)
  37.  
  38.    char sign = 0;
  39.    int i = 0;
  40.  
  41.    switch (*s)        // remember the sign
  42. {
  43. case '+':
  44. case '-':
  45.     sign = *s++;
  46.     break;
  47. }
  48.  
  49.    // for positive numbers on a 2's complement machine,
  50.    // the minimum # is -INT_MAX, not INT_MIN
  51.    const int int_min = (TWOSCOMPLEMENT && (sign != '-')) ?
  52.         (-INT_MAX) : INT_MIN;
  53.  
  54.    switch (*s)
  55. {
  56. case '0':        // hex or octal
  57.     switch (*++s)
  58.     {
  59.     case 'x':        // hex number
  60.     case 'X':
  61.         for (s++; isxdigit(*s); s++)
  62.         {
  63.         if (-i > INT_MAX / 16)
  64.             break;
  65.         i *= 16;
  66.         int n = hexvalue(*s);
  67.         if (i < int_min + n)
  68.             break;
  69.         i -= n;
  70.         }
  71.  
  72.         if (isxdigit(*s))
  73.             error("integer overflow");
  74.         break;
  75.  
  76.     default:        // octal number
  77.         for ( ; isodigit(*s); s++)
  78.         {
  79.         if (-i > INT_MAX / 8)
  80.             break;
  81.         i *= 8;
  82.         int n = *s - '0';
  83.         if (i < int_min + n)
  84.             break;
  85.         i -= n;
  86.         }
  87.  
  88.         if (isodigit(*s))
  89.             error("integer overflow");
  90.         break;
  91.     }
  92.     break;
  93.  
  94. case '\\':        // char constant
  95.     if (sign == 0)
  96.     {
  97.     switch (*++s)
  98.         {
  99.         case 'x':    // \xXXX -> hex
  100.         for (int n = 3;
  101.              isxdigit(*++s) && n-- > 0;
  102.              )
  103.             i = i * 16 - hexvalue(*s);
  104.         break;
  105.  
  106.         // single character constants
  107.         case 'b':    i = -'\b'; s++; break;
  108.         case 'f':    i = -'\f'; s++; break;
  109.         case 'n':    i = -'\n'; s++; break;
  110.         case 'r':    i = -'\r'; s++; break;
  111.         case 't':    i = -'\t'; s++; break;
  112.         case 'v':    i = -'\v'; s++; break;
  113.         case '\\':    i = -'\\'; s++; break;
  114.         case '\'':    i = -'\''; s++; break;
  115.         case '"':    i = -'\"'; s++; break;
  116.         case '0':    i =  '\0'; s++; break;
  117.  
  118.         default:    // \XXX -> octal
  119.         for (n = 3;
  120.              isodigit(*s) && n-- > 0;
  121.              s++)
  122.             i = i * 8 - (*s - '0');
  123.         break;
  124.         }
  125.     }
  126.  
  127.     else
  128.     error("char constant with sign");
  129.     break;
  130.  
  131. default:        // decimal number
  132.     for ( ; isdigit(*s); s++)
  133.         {
  134.     if (-i > INT_MAX / 10)
  135.         break;
  136.     i *= 10;
  137.     int n = *s - '0';
  138.     if (i < int_min + n)
  139.         break;
  140.     i -= n;
  141.     }
  142.  
  143.     if (isdigit(*s))
  144.         error("integer overflow");
  145.     break;
  146. }
  147.  
  148.    if (*s)
  149. error("malformed integer");
  150.    return sign == '-' ? i : -i;
  151.  
  152.